package com.company.ems.controller;

import com.company.ems.dto.EmployeeQueryDTO;
import com.company.ems.dto.PageDTO;
import com.company.ems.mapper.EmployeeMapper;
import com.company.ems.model.Employee;
import com.company.ems.model.User;
import com.company.ems.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;

@WebServlet("/employees")
public class EmployeeServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String action = request.getParameter("action");

        if ("view".equals(action)) {
            viewEmployee(request, response);
        } else if ("edit".equals(action)) {
            editEmployeeForm(request, response);
        } else if ("add".equals(action)) {
            addEmployeeForm(request, response);
        } else {
            listEmployees(request, response);
        }
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String action = request.getParameter("action");

        if ("add".equals(action)) {
            addEmployee(request, response);
        } else if ("update".equals(action)) {
            updateEmployee(request, response);
        } else if ("delete".equals(action)) {
            deleteEmployee(request, response);
        } else {
            listEmployees(request, response);
        }
    }

    private void listEmployees(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        EmployeeQueryDTO query = new EmployeeQueryDTO();
        query.setName(request.getParameter("name"));
        query.setDepartment(request.getParameter("department"));
        query.setPosition(request.getParameter("position"));

        String pageStr = request.getParameter("page");
        if (pageStr != null && !pageStr.isEmpty()) {
            query.setPage(Integer.parseInt(pageStr));
        }

        try (SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
            EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);

            List<Employee> employees = employeeMapper.findAll(query);
            int total = employeeMapper.count(query);

            PageDTO<Employee> page = new PageDTO<>(employees, total, query.getPage(), query.getPageSize());

            request.setAttribute("employees", employees);
            request.setAttribute("page", page);
            request.setAttribute("query", query);

            request.getRequestDispatcher("/employee/list.jsp").forward(request, response);
        }
    }

    private void viewEmployee(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        Integer id = Integer.parseInt(request.getParameter("id"));

        try (SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
            EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
            Employee employee = employeeMapper.findById(id);

            request.setAttribute("employee", employee);
            request.getRequestDispatcher("/employee/view.jsp").forward(request, response);
        }
    }

    private void addEmployeeForm(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.getRequestDispatcher("/employee/add.jsp").forward(request, response);
    }

    private void editEmployeeForm(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        Integer id = Integer.parseInt(request.getParameter("id"));

        try (SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
            EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
            Employee employee = employeeMapper.findById(id);

            request.setAttribute("employee", employee);
            request.getRequestDispatcher("/employee/edit.jsp").forward(request, response);
        }
    }

    private void addEmployee(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        HttpSession session = request.getSession();
        User loggedInUser = (User) session.getAttribute("loggedInUser");

        Employee employee = new Employee();
        employee.setName(request.getParameter("name"));
        employee.setDepartment(request.getParameter("department"));
        employee.setPosition(request.getParameter("position"));
        employee.setSalary(new BigDecimal(request.getParameter("salary")));
        employee.setEmail(request.getParameter("email"));
        employee.setPhone(request.getParameter("phone"));
        employee.setHireDate(LocalDate.parse(request.getParameter("hireDate")));
        employee.setCreatedBy(loggedInUser.getId());

        try (SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
            EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
            employeeMapper.insert(employee);
            sqlSession.commit();
        }

        response.sendRedirect(request.getContextPath() + "/employees");
    }

    private void updateEmployee(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        Employee employee = new Employee();
        employee.setId(Integer.parseInt(request.getParameter("id")));
        employee.setName(request.getParameter("name"));
        employee.setDepartment(request.getParameter("department"));
        employee.setPosition(request.getParameter("position"));
        employee.setSalary(new BigDecimal(request.getParameter("salary")));
        employee.setEmail(request.getParameter("email"));
        employee.setPhone(request.getParameter("phone"));
        employee.setHireDate(LocalDate.parse(request.getParameter("hireDate")));

        try (SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
            EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
            employeeMapper.update(employee);
            sqlSession.commit();
        }

        response.sendRedirect(request.getContextPath() + "/employees");
    }

    private void deleteEmployee(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        Integer id = Integer.parseInt(request.getParameter("id"));

        try (SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
            EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
            employeeMapper.delete(id);
            sqlSession.commit();
        }

        response.sendRedirect(request.getContextPath() + "/employees");
    }
}